//
//  Diamond.swift
//  1010
//
//  Created by 米明 on 15/7/8.
//  Copyright (c) 2015年 米明. All rights reserved.
//

import UIKit

//不同的方块

enum DiamondNumber : Int { //小方块个数
    case D1=1 //一个块
    case D2 //一字 纵、横
    case D3 //一字 纵、横 L 四个方向
    case D4 //田字、一字 纵横
    case D5 //一字 纵、横 L 四个方向
    case D9=9 //九宫格
}

enum DiamondDirection : Int { //小方块方向
    case None=0 //无方向
    case Vertical // —— 纵向
    case Horizontal // | 横向
    case LeftUp    // ┘
    case LeftDown  //┐
    case RightUp   // └
    case RightDown //┌
}

//以上分析得出一共有 (1)+(2)+(2+4)+(1+2)+(2+4)+(1)= 19 种类型的方块

class Diamond: UIView {
    
    var diamondNumber:DiamondNumber?
    var diamondDirection:DiamondDirection?
    var originalCenter:CGPoint!
    
    var isEmpty: CallBack!
    var gameOver: CallBack!//游戏结束回调
    var reloadScore: CallBack!//更新分数
    
    var number: DiamondNumber {
        set {
            self.diamondNumber=newValue
            self.diamondDirection = randomDirectionByNumber(number: newValue)
            print("方块个数 \(self.diamondNumber!.rawValue) & 方向 \(self.diamondDirection!.rawValue)")
            
            resetFrame()
            drawDiamond()
            
        }
        get {
            return self.diamondNumber!
        }
    }
    
    //当前小方块宽
    var diamondWidth = CGFloat(0)
    
    @discardableResult func produceDiamond(_ frame:CGRect) -> UIView {
        let d = UIView(frame: frame)
        d.backgroundColor=color()
        d.layer.borderColor=UIColor.white.cgColor
        d.layer.borderWidth=1
        d.layer.masksToBounds=true
        d.layer.cornerRadius=d.frame.size.width*0.1
        self.addSubview(d)
        diamondWidth = d.frame.size.width
        return d
    }
    
    //MARK:画小方块
    func drawDiamond() {
        let nowSize = self.frame.size
        
        switch number {
        case .D1:
            produceDiamond(CGRect(x: self.frame.size.width/3.0, y: self.frame.size.width/3.0, width: self.frame.size.width/3.0, height: self.frame.size.width/3.0))
        case .D2:
            
            switch direction {
                
            case .Vertical: // |
                
                for i in 0...1 {
                    produceDiamond(CGRect(x: self.frame.size.width/3.0, y: self.frame.size.width/6.0+CGFloat(i)*self.frame.size.width/3.0, width: self.frame.size.width/3.0, height: self.frame.size.width/3.0))
                }
            case .Horizontal: // -
                
                for i in 0...1 {
                    produceDiamond(CGRect(x: self.frame.size.width/6.0+CGFloat(i)*self.frame.size.width/3.0,y: self.frame.size.width/3.0, width: self.frame.size.width/3.0, height: self.frame.size.width/3.0))
                }
            default :break
            }
            
            
        case .D3:
            
            switch direction {
            case .Vertical:
                
                for i in 0...2 {
                    produceDiamond(CGRect(x: self.frame.size.width/3.0,y: CGFloat(i)*self.frame.size.width/3.0, width: self.frame.size.width/3.0, height: self.frame.size.width/3.0))
                }
            case .Horizontal:
                for i in 0...2 {
                    produceDiamond(CGRect(x: CGFloat(i)*self.frame.size.width/3.0,y: self.frame.size.width/3.0, width: self.frame.size.width/3.0, height: self.frame.size.width/3.0))
                }
            case .LeftUp , .LeftDown , .RightUp , .RightDown:
                
                for i in 3...6 {
                    if direction.rawValue==i {
                        continue
                    }else{
                        produceDiamond(CGRect(x: self.frame.size.width/6.0+self.frame.size.width/3.0*CGFloat((i-3)/2),y: self.frame.size.width/6.0+CGFloat((i-3)%2)*self.frame.size.width/3.0, width: self.frame.size.width/3.0, height: self.frame.size.width/3.0))
                    }
                }
            default :break
            }
            
        case .D4:
            switch direction {
            case .None:
                let dWidth = nowSize.width/4.0
                for i in 0...3 {
                    produceDiamond(CGRect(x: dWidth+CGFloat(i/2)*dWidth,y: dWidth+CGFloat(i%2)*dWidth, width: dWidth, height: dWidth))
                }
            case .Vertical:
                let dWidth = nowSize.width/4.0
                for i in 0...3 {
                    produceDiamond(CGRect(x: dWidth*1.5,y: CGFloat(i)*dWidth, width: dWidth, height: dWidth))
                }
            case .Horizontal:
                let dWidth = nowSize.width/4.0
                for i in 0...3 {
                    produceDiamond(CGRect(x: CGFloat(i)*dWidth,y: dWidth*1.5, width: dWidth, height: dWidth))
                }
            default :break
            }
        case .D5:
            switch direction {
            case .Vertical:
                let dWidth = nowSize.width/5.0
                for i in 0...4 {
                    produceDiamond(CGRect(x: dWidth*2,y: CGFloat(i)*dWidth, width: dWidth, height: dWidth))
                }
            case .Horizontal:
                let dWidth = nowSize.width/5.0
                for i in 0...4 {
                    produceDiamond(CGRect(x: CGFloat(i)*dWidth,y: dWidth*2, width: dWidth, height: dWidth))
                }
            case .LeftUp , .LeftDown , .RightUp , .RightDown:
                let dWidth = nowSize.width/3.0
                for i in 0...2 {
                    for j in 0...2 {
                        if direction == .LeftUp && (i==2 || j==2) {
                            produceDiamond(CGRect(x: CGFloat(i)*dWidth,y: CGFloat(j)*dWidth, width: dWidth, height: dWidth))
                        }
                        else if direction == .LeftDown && (i==2 || j==0) {
                            produceDiamond(CGRect(x: CGFloat(i)*dWidth,y: CGFloat(j)*dWidth, width: dWidth, height: dWidth))
                            
                        }else if direction == .RightUp && (i==0 || j==2) {
                            produceDiamond(CGRect(x: CGFloat(i)*dWidth,y: CGFloat(j)*dWidth, width: dWidth, height: dWidth))
                            
                        }else if direction == .RightDown && (i==0 || j==0) {
                            produceDiamond(CGRect(x: CGFloat(i)*dWidth,y: CGFloat(j)*dWidth, width: dWidth, height: dWidth))
                            
                        }
                    }
                }
            default :break
            }
        case .D9:
            let dWidth = nowSize.width/3.0
            for i in 0...2 {
                for j in 0...2 {
                    produceDiamond(CGRect(x: CGFloat(i)*dWidth,y: CGFloat(j)*dWidth, width: dWidth, height: dWidth))
                    
                }
            }
            
      //  default: break
        }
        
        
    }
    
    //MARK:根据number direction重新设置frame
    func resetFrame() {
        
        var newSize = self.frame.size
        let diamondWidth = newSize.width/3.0
        
        switch number {
        case .D1:
            
            //无方向
            newSize=CGSize(width: 3*diamondWidth, height: 3*diamondWidth)
            
            
        case .D2:
            
            switch direction {
            case .Vertical: // |
                newSize=CGSize(width: 3*diamondWidth, height: 3*diamondWidth)
            case .Horizontal: // -
                newSize=CGSize(width: 3*diamondWidth, height: 3*diamondWidth)
            default :break
            }
            
        case .D3:
            switch direction {
            case .Vertical:
                newSize=CGSize(width: diamondWidth*3, height: diamondWidth*3)
            case .Horizontal:
                newSize=CGSize(width: diamondWidth*3, height: diamondWidth*3)
            case .LeftUp , .LeftDown , .RightUp , .RightDown:
                newSize=CGSize(width: diamondWidth*3, height: diamondWidth*3)
            default :break
            }
            
        case .D4:
            switch direction {
            case .None:
                newSize=CGSize(width: diamondWidth*3, height: diamondWidth*3)
            case .Vertical:
                newSize=CGSize(width: diamondWidth*3, height: diamondWidth*3)
            case .Horizontal:
                newSize=CGSize(width: diamondWidth*3, height: diamondWidth*3)
            default :break
            }
        case .D5:
            switch direction {
            case .Vertical:
                newSize=CGSize(width: diamondWidth*5, height: diamondWidth*5)
            case .Horizontal:
                newSize=CGSize(width: diamondWidth*5, height: diamondWidth*5)
            case .LeftUp , .LeftDown , .RightUp , .RightDown:
                newSize=CGSize(width: diamondWidth*3, height: diamondWidth*3)
            default :break
            }
        case .D9:
            newSize=CGSize(width: diamondWidth*3, height: diamondWidth*3)
            
       // default: break
        }
        self.frame.size = newSize
    }
    
    //动画结束时赋值
    func setCenter() {
        originalCenter = self.center
        addPanGesture()
    }
    
    //MARK:根据number 设置 direction
    func randomDirectionByNumber(number: DiamondNumber) -> DiamondDirection {
        
        switch number {
        case .D1: return .None
        case .D2:
            //随机数 0-1
            let rand = arc4random()%2
            if rand == 0 {//纵
                return .Vertical
            }else{//横
                return .Horizontal
            }
        case .D3 , .D5:
            
            //随机数0-5
            let rand = arc4random()%6
            switch rand {
            case 0:return .Vertical
            case 1:return .Horizontal
            case 2:return .LeftUp
            case 3:return .LeftDown
            case 4:return .RightUp
            case 5:return .RightDown
            default : return .None
            }
        case .D4:
            //随机数0-2
            let rand = arc4random()%3
            switch rand {
            case 0:return .None
            case 1:return .Vertical
            case 2:return .Horizontal
            default : return .None
            }
        case .D9:
            return .None
            
        //default : return .None
        }
    }
    
    
    var direction: DiamondDirection {
        set {
            self.layer.borderColor = UIColor.orange.cgColor
            diamondDirection = newValue
        }
        get {
            return diamondDirection!
        }
    }
    
    
    //MARK: 小方块颜色
    func color() -> UIColor {
        switch number {
        case .D1:
            return customColor(red: 253, green: 118, blue: 101, alpha: 1)
        case .D2:
            return customColor(red: 92, green: 152, blue: 114, alpha: 1)
        case .D3:
            switch direction {
            case .Vertical , .Horizontal:
                return customColor(red: 176, green: 221, blue: 108, alpha: 1)
            case .LeftUp , .LeftDown , .RightUp , .RightDown:
                return customColor(red: 90, green: 141, blue: 72, alpha: 1)
            default :break
            }
            
        case .D4:
            switch direction {
            case .None:
                return customColor(red: 236, green: 102, blue: 58, alpha: 1)
            case .Vertical , .Horizontal:
                return customColor(red: 198, green: 121, blue: 13, alpha: 1)
            default :break
            }
        case .D5:
            switch direction {
            case .Vertical , .Horizontal:
                return customColor(red: 134, green: 58, blue: 187, alpha: 1)
            case .LeftUp , .LeftDown , .RightUp , .RightDown:
                return customColor(red: 190, green: 135, blue: 217, alpha: 1)
            default :break
            }
        case .D9:
            return customColor(red: 146, green: 212, blue: 229, alpha: 1)
       // default: break
        }
        return UIColor.clear
    }
    
    //MARK: 初始化
    init(frame: CGRect , type: Int) {super.init(frame: frame)}
    override init(frame: CGRect) {super.init(frame: frame)}
    required init?(coder aDecoder: NSCoder) {super.init(coder: aDecoder)}
    
    //MARK: 拖拽手势
    var panGestureRecognizer:UIPanGestureRecognizer?
    
    func addPanGesture() {
        //拖拽
        panGestureRecognizer=UIPanGestureRecognizer(target: self, action: #selector(handlePanGestures(_:)))
        panGestureRecognizer?.minimumNumberOfTouches=1
        panGestureRecognizer?.maximumNumberOfTouches=1
        addGestureRecognizer(panGestureRecognizer!)
    }
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        enlarge()//变大
    }
    
    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        resume()
    }
    
    //拖拽回调
    @objc func handlePanGestures(_ panSender: UIPanGestureRecognizer) {
        
        if panSender.state == .began {
            print(self.center)
        }else if panSender.state == UIGestureRecognizer.State.changed {
            let location = panSender.location(in: self.superview)
            
            UIView.animate(withDuration: 0.1, animations: {
                self.center=CGPoint(x: location.x, y: location.y - self.frame.size.height/2.0-40)
                }) { (finished) -> Void in
                    
            }
            
            //println("Changed (x,y) = \(location.x, location.y)")
        }else if panSender.state == .ended {
            let location = panSender.location(in: self.superview)
            
            print(location)
            
            //条件判断
            //1.是否在棋盘上
            if !aboveGameView() {
                //不在棋盘上还原
                resume()
                
            }else{
                //监测与哪一个格子相交
                checkAboveSquare()
                //监测是否 有满行
                //读取消除的行数
                let number = checkFillNumber()
                
                //计算分数
                var score = number*number*2
                
                if (reloadScore != nil) && number > 0 {
                    //存分数
                    score += DataCenter.nowScore()
                    DataCenter.setNowScore(score: score)
                    //刷新计分板
                    reloadScore!()
                    
                    //消除的行数
                    LYBadgeView.showMessage(score: number)
                }
                
                //消除满行
                clearFillSquares()
            }
            
            //监测gameOver条件
            //无法将剩余的diamond 放在棋盘上
            
            //延时
            DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
                if self.checkGameOver() {
                    self.gameOver!()
                }
            }
            
        }
    }
    
    //MARK: 监测与哪一个格子相交
    func checkAboveSquare() {
        
        for sq in squares {
            //println("\(sq.tag)")
            
            if sq.frame.contains(self.center) {
                print("Square Tag \(sq.tag)")
                //中心点落在的格子上 是否可以创建该类型的diamond
                if checkOnSquarePoint(sq: sq) == false {
                    resume()
                }
                break
            }
        }
    }
    
    //MARK: 判断是否落在棋盘上
    func aboveGameView() -> Bool {
        if gameView.frame.contains(self.center) {
            return true
        }else{
            return false
        }
    }
    
    //leftup leftdown rightup rightdown
    //MARK: 根据diamond类型 判断其中心在格子上的方位
    func checkOnSquarePoint(sq:UIView) -> Bool {
        
        let index = sq.tag
        
        switch self.number {
        case .D1://该格子是否有diamond
            switch self.direction {
            case .None:
                if  outOfRange(index) {//如果没有 在该位置 创建diamond 状态计为1
                    produceSqure(index)
                    
                }else{//如何已经 有了
                    return false //恢复
                }
            default :break
            }
        case .D2:
            switch self.direction {
            case .Vertical:
                
                if self.center.y<=sq.center.y {
                    if outOfRange(index-10)
                        && outOfRange(index) {
                            produceSqure(index)
                            produceSqure(index-10)
                    }else{
                        return false
                    }
                }else if self.center.y>sq.center.y {
                    if outOfRange(index+10)
                        && outOfRange(index) {
                            produceSqure(index)
                            produceSqure(index+10)
                    }else{
                        return false
                    }
                }
            case .Horizontal:
                if self.center.x<=sq.center.x {
                    if outOfRange(index-1)
                        && outOfRange(index)
                    {//排除边界情况
                        produceSqure(index)
                        produceSqure(index-1)
                    }else {
                        return false
                    }
                    
                    
                }else if self.center.x>sq.center.x  {
                    if outOfRange(index+1)
                        && outOfRange(index)
                    {
                        produceSqure(index)
                        produceSqure(index+1)
                    }else{
                        return false
                    }
                }
                
            default:break
            }
        case .D3:
            switch self.direction {
            case .Vertical:
                if outOfRange(index+10)
                    && outOfRange(index-10)
                    && outOfRange(index) {
                        produceSqure(index+10)
                        produceSqure(index-10)
                        produceSqure(index)
                }else{
                    return false
                }
            case .Horizontal:
                
                if outOfRange(index+1)
                    && outOfRange(index-1)
                    && outOfRange(index){
                        
                        
                        produceSqure(index+1)
                        produceSqure(index-1)
                        produceSqure(index)
                        
                        
                }else{
                    return false
                }
            case .LeftUp:
                
                if self.center.x <= sq.center.x
                    && self.center.y <= sq.center.y {
                        if outOfRange(index-1)
                            && outOfRange(index-10)
                            && outOfRange(index)
                        {
                            produceSqure(index)
                            produceSqure(index-1)
                            produceSqure(index-10)
                        }else{
                            return false
                        }
                }else if self.center.x <= sq.center.x
                    && self.center.y > sq.center.y {
                        if outOfRange(index+9)
                            && outOfRange(index+10)
                            && outOfRange(index)
                        {
                            
                            produceSqure(index)
                            produceSqure(index+9)
                            produceSqure(index+10)
                            
                            
                        }else{
                            return false
                        }
                }else if self.center.x > sq.center.x
                    && self.center.y <= sq.center.y {
                        if outOfRange(index+1)
                            && outOfRange(index-9)
                            && outOfRange(index)
                        {
                            produceSqure(index)
                            produceSqure(index-9)
                            produceSqure(index+1)
                        }else{
                            return false
                        }
                }else  if self.center.x > sq.center.x
                    && self.center.y > sq.center.y {
                        if outOfRange(index+1)
                            && outOfRange(index+10)
                            && outOfRange(index+11)
                        {
                            
                            produceSqure(index+1)
                            produceSqure(index+11)
                            produceSqure(index+10)
                            
                            
                        }else{
                            return false
                        }
                }
            case .LeftDown:
                
                if self.center.x <= sq.center.x
                    && self.center.y <= sq.center.y {
                        if outOfRange(index-11)
                            && outOfRange(index-10)
                            && outOfRange(index)
                        {
                            produceSqure(index)
                            produceSqure(index-11)
                            produceSqure(index-10)
                        }else{
                            return false
                        }
                }else if self.center.x <= sq.center.x
                    && self.center.y > sq.center.y {
                        if outOfRange(index-1)
                            && outOfRange(index+10)
                            && outOfRange(index)
                        {
                            produceSqure(index)
                            produceSqure(index-1)
                            produceSqure(index+10)
                        }else{
                            return false
                        }
                }else if self.center.x > sq.center.x
                    && self.center.y <= sq.center.y {
                        if outOfRange(index+1)
                            && outOfRange(index-9)
                            && outOfRange(index-10)
                        {
                            produceSqure(index+1)
                            produceSqure(index-9)
                            produceSqure(index-10)
                        }else{
                            return false
                        }
                }else if self.center.x > sq.center.x
                    && self.center.y > sq.center.y {
                        if outOfRange(index+1)
                            && outOfRange(index+11)
                            && outOfRange(index)
                        {
                            produceSqure(index+1)
                            produceSqure(index+11)
                            produceSqure(index)
                        }else{
                            return false
                        }
                }
            case .RightUp:
                
                if self.center.x <= sq.center.x
                    && self.center.y <= sq.center.y {
                        if outOfRange(index-11)
                            && outOfRange(index-1)
                            && outOfRange(index)
                        {
                            produceSqure(index)
                            produceSqure(index-11)
                            produceSqure(index-1)
                        }else{
                            return false
                        }
                }else if self.center.x <= sq.center.x
                    && self.center.y > sq.center.y {
                        if outOfRange(index-1)
                            && outOfRange(index+10)
                            && outOfRange(index+9)
                        {
                            
                            produceSqure(index+9)
                            produceSqure(index-1)
                            produceSqure(index+10)
                            
                            
                        }else{
                            return false
                        }
                }else if self.center.x > sq.center.x
                    && self.center.y <= sq.center.y {
                        if outOfRange(index+1)
                            && outOfRange(index-10)
                            && outOfRange(index)
                        {
                            produceSqure(index+1)
                            produceSqure(index)
                            produceSqure(index-10)
                        }else{
                            return false
                        }
                }else if self.center.x > sq.center.x
                    && self.center.y > sq.center.y {
                        if outOfRange(index+10)
                            && outOfRange(index+11)
                            && outOfRange(index)
                        {
                            
                            produceSqure(index+10)
                            produceSqure(index+11)
                            produceSqure(index)
                            
                            
                        }else{
                            return false
                        }
                }
            case .RightDown:
                
                if self.center.x <= sq.center.x
                    && self.center.y <= sq.center.y {
                        if outOfRange(index-11)
                            && outOfRange(index-1)
                            && outOfRange(index-10)
                        {
                            produceSqure(index-10)
                            produceSqure(index-11)
                            produceSqure(index-1)
                        }else{
                            return false
                        }
                }else if self.center.x <= sq.center.x
                    && self.center.y > sq.center.y {
                        if outOfRange(index-1)
                            && outOfRange(index+9)
                            && outOfRange(index)
                        {
                            produceSqure(index+9)
                            produceSqure(index-1)
                            produceSqure(index)
                        }else{
                            return false
                        }
                }else if self.center.x > sq.center.x
                    && self.center.y <= sq.center.y {
                        if outOfRange(index-9)
                            && outOfRange(index-10)
                            && outOfRange(index)
                        {
                            produceSqure(index)
                            produceSqure(index-9)
                            produceSqure(index-10)
                        }else{
                            return false
                        }
                }else if self.center.x > sq.center.x
                    && self.center.y > sq.center.y {
                        if outOfRange(index+10)
                            && outOfRange(index+1)
                            && outOfRange(index)
                        {
                            produceSqure(index+10)
                            produceSqure(index+1)
                            produceSqure(index)
                        }else{
                            return false
                        }
                }
            default : break
            }
        case .D4:
            switch self.direction {
            case .Vertical:
                if self.center.y > sq.center.y {
                    if outOfRange(index)
                        && outOfRange(index-10)
                        && outOfRange(index+10)
                        && outOfRange(index+20) {
                            produceSqure(index+20)
                            produceSqure(index-10)
                            produceSqure(index)
                            produceSqure(index+10)
                    }else{
                        return false
                    }
                }else if self.center.y <= sq.center.y {
                    if outOfRange(index)
                        && outOfRange(index-10)
                        && outOfRange(index+10)
                        && outOfRange(index-20) {
                            produceSqure(index-20)
                            produceSqure(index-10)
                            produceSqure(index)
                            produceSqure(index+10)
                    }else{
                        return false
                    }
                }
            case .Horizontal:
                if self.center.x <= sq.center.x {
                    if outOfRange(index)
                        && outOfRange(index-1)
                        && outOfRange(index+1)
                        && outOfRange(index-2)
                    {
                        
                        produceSqure(index+1)
                        produceSqure(index-1)
                        produceSqure(index)
                        produceSqure(index-2)
                        
                    }else{
                        return false
                    }
                    
                }else if self.center.x > sq.center.x {
                    if outOfRange(index)
                        && outOfRange(index-1)
                        && outOfRange(index+1)
                        && outOfRange(index+2)
                    {
                        
                        produceSqure(index+2)
                        produceSqure(index-1)
                        produceSqure(index)
                        produceSqure(index+1)
                        
                        
                    }else{
                        return false
                    }
                }
            case .None:
                if self.center.x <= sq.center.x
                    && self.center.y <= sq.center.y {
                        if outOfRange(index)
                            && outOfRange(index-1)
                            && outOfRange(index-11)
                            && outOfRange(index-10)
                        {
                            
                            produceSqure(index-1)
                            produceSqure(index-11)
                            produceSqure(index)
                            produceSqure(index-10)
                            
                            
                        }else{
                            return false
                        }
                }else if self.center.x <= sq.center.x
                    && self.center.y > sq.center.y {
                        if outOfRange(index)
                            && outOfRange(index-1)
                            && outOfRange(index+9)
                            && outOfRange(index+10)
                        {
                            
                            produceSqure(index-1)
                            produceSqure(index+9)
                            produceSqure(index)
                            produceSqure(index+10)
                            
                            
                        }else{
                            return false
                        }
                }else if self.center.x > sq.center.x
                    && self.center.y <= sq.center.y {
                        if outOfRange(index)
                            && outOfRange(index+1)
                            && outOfRange(index-10)
                            && outOfRange(index-9)
                        {
                            
                            produceSqure(index+1)
                            produceSqure(index-10)
                            produceSqure(index)
                            produceSqure(index-9)
                            
                            
                        }else{
                            return false
                        }
                }else if self.center.x > sq.center.x
                    && self.center.y > sq.center.y {
                        if outOfRange(index)
                            && outOfRange(index+1)
                            && outOfRange(index+11)
                            && outOfRange(index+10)
                        {
                            
                            produceSqure(index+1)
                            produceSqure(index+11)
                            produceSqure(index)
                            produceSqure(index+10)
                            
                            
                        }else{
                            return false
                        }
                }
            default :break
            }
        case .D5:
            switch self.direction {
            case .Vertical:
                if outOfRange(index+10)
                    && outOfRange(index+20)
                    && outOfRange(index-10)
                    && outOfRange(index-20)
                    && outOfRange(index) {
                        produceSqure(index+10)
                        produceSqure(index+20)
                        produceSqure(index-10)
                        produceSqure(index-20)
                        produceSqure(index)
                }else{
                    return false
                }
            case .Horizontal:
                if outOfRange(index+1)
                    && outOfRange(index+2)
                    && outOfRange(index-1)
                    && outOfRange(index-2)
                    && outOfRange(index)
                {
                    
                    produceSqure(index+1)
                    produceSqure(index+2)
                    produceSqure(index-1)
                    produceSqure(index-2)
                    produceSqure(index)
                    
                }else{
                    return false
                }
            case .LeftUp:
                if outOfRange(index+9)
                    && outOfRange(index-9)
                    && outOfRange(index+11)
                    && outOfRange(index+1)
                    && outOfRange(index+10)
                {
                    
                    produceSqure(index+9)
                    produceSqure(index-9)
                    produceSqure(index+11)
                    produceSqure(index+1)
                    produceSqure(index+10)
                    
                    
                }else{
                    return false
                }
            case .LeftDown:
                if outOfRange(index-10)
                    && outOfRange(index-9)
                    && outOfRange(index-11)
                    && outOfRange(index+1)
                    && outOfRange(index+11)
                {
                    produceSqure(index-11)
                    produceSqure(index-9)
                    produceSqure(index+11)
                    produceSqure(index+1)
                    produceSqure(index-10)
                }else{
                    return false
                }
            case .RightUp:
                if outOfRange(index-1)
                    && outOfRange(index-11)
                    && outOfRange(index+11)
                    && outOfRange(index+9)
                    && outOfRange(index+10)
                {
                    
                    produceSqure(index+9)
                    produceSqure(index+10)
                    produceSqure(index+11)
                    produceSqure(index-11)
                    produceSqure(index-1)
                    
                    
                }else{
                    return false
                }
            case .RightDown:
                if outOfRange(index-1)
                    && outOfRange(index-11)
                    && outOfRange(index-10)
                    && outOfRange(index-9)
                    && outOfRange(index+9)
                {
                    produceSqure(index+9)
                    produceSqure(index-9)
                    produceSqure(index-1)
                    produceSqure(index-11)
                    produceSqure(index-10)
                }else{
                    return false
                }
            default :break
            }
        case .D9:
            switch self.direction {
            case .None:
                if outOfRange(index+1)
                    && outOfRange(index-1)
                    && outOfRange(index-10)
                    && outOfRange(index+10)
                    && outOfRange(index+11)
                    && outOfRange(index-11)
                    && outOfRange(index)
                    && outOfRange(index-9)
                    && outOfRange(index+9)
                {
                    
                    produceSqure(index+1)
                    produceSqure(index-1)
                    produceSqure(index-10)
                    produceSqure(index+10)
                    produceSqure(index-11)
                    produceSqure(index+11)
                    produceSqure(index)
                    produceSqure(index-9)
                    produceSqure(index+9)
                }else{
                    return false
                }
            default:break
            }
        //default :break
        }
        
        print("\(squareStatus)")
        
        self.removeFromSuperview()
        
        //从数组中删除
        removeFromDiamonds()
        
        //如果三个diamond 没有了 则重新创建
        if diamonds.count == 0 {
            print("创建Diamonds")
            // diamonds数组为空时回调
            isEmpty!()
            
        }
        
        return false
    }
    
    //MARK: gameOver 条件
    func checkGameOver() -> Bool {
        print("监测gameOver")
        var tmp = 0
        for diamond in diamonds {
            for sq in squares {
                if canPlace(sq,diamond:diamond) {
                    tmp += 1
                }
            }
        }
        if tmp>0 {
            return false
        }else{
            return true
        }
    }
    
    //MARK: 监测是否可以放置剩余的diamond
    func canPlace(_ sq: UIView ,diamond: Diamond) -> Bool {
        let number = diamond.number
        let direction = diamond.direction
        let index = sq.tag
        switch number {
        case .D1:
            if outOfRange(sq.tag) {
                return true
            }else{
                return false
            }
        case .D2:
            switch direction {
            case .Vertical:
                if diamond.center.y<=sq.center.y {
                    if outOfRange(index-10) && outOfRange(index) {
                        return true
                    }else{
                        return false
                    }
                }else if diamond.center.y>sq.center.y {
                    if outOfRange(index+10) && outOfRange(index) {
                        return true
                    }else{
                        return false
                    }
                }
            case .Horizontal:
                if diamond.center.x<=sq.center.x {
                    if outOfRange(index-1)
                        && outOfRange(index)  {
                            return true
                    }else {
                        return false
                    }
                    
                    
                }else if diamond.center.x>sq.center.x  {
                    if outOfRange(index+1)
                        && outOfRange(index) {
                            return true
                    }else{
                        return false
                    }
                }
            default : break
            }
        case .D3:
            switch direction {
            case .Vertical:
                if outOfRange(index+10)
                    && outOfRange(index-10)
                    && outOfRange(index) {
                        return true
                }else{
                    return false
                }
            case .Horizontal:
                
                if outOfRange(index+1)
                    && outOfRange(index-1)
                    && outOfRange(index)
                    
                {
                    
                    return true
                    
                }else{
                    return false
                }
            case .LeftUp:
                if diamond.center.x <= sq.center.x && diamond.center.y <= sq.center.y {
                    if outOfRange(index-1)
                        && outOfRange(index-10)
                        && outOfRange(index)
                    {
                        return true
                    }else{
                        return false
                    }
                }else if diamond.center.x <= sq.center.x && diamond.center.y > sq.center.y {
                    if outOfRange(index+9)
                        && outOfRange(index+10)
                        && outOfRange(index)
                    {
                        return true
                    }else{
                        return false
                    }
                }else if diamond.center.x > sq.center.x && diamond.center.y <= sq.center.y {
                    if outOfRange(index-1)
                        && outOfRange(index-10)
                        && outOfRange(index)
                    {
                        return true
                    }else{
                        return false
                    }
                }else  if diamond.center.x > sq.center.x && diamond.center.y > sq.center.y {
                    if outOfRange(index+1)
                        && outOfRange(index+10)
                        && outOfRange(index+11) {
                            return true
                    }else{
                        return false
                    }
                }
            case .LeftDown:
                if diamond.center.x <= sq.center.x && diamond.center.y <= sq.center.y {
                    if outOfRange(index-11)
                        && outOfRange(index-10)
                        && outOfRange(index)
                    {
                        return true
                    }else{
                        return false
                    }
                }else if diamond.center.x <= sq.center.x && diamond.center.y > sq.center.y {
                    if outOfRange(index-1)
                        && outOfRange(index+10)
                        && outOfRange(index)
                    {
                        return true
                    }else{
                        return false
                    }
                }else if diamond.center.x > sq.center.x && diamond.center.y <= sq.center.y {
                    if outOfRange(index+1)
                        && outOfRange(index-9)
                        && outOfRange(index-10)
                    {
                        return true
                    }else{
                        return false
                    }
                }else if diamond.center.x > sq.center.x && diamond.center.y > sq.center.y {
                    if outOfRange(index+1)
                        && outOfRange(index+11)
                        && outOfRange(index)
                    {
                        return true
                    }else{
                        return false
                    }
                }
            case .RightUp:
                if diamond.center.x <= sq.center.x && diamond.center.y <= sq.center.y {
                    if outOfRange(index-11)
                        && outOfRange(index-1)
                        && outOfRange(index)
                    {
                        return true
                    }else{
                        return false
                    }
                }else if diamond.center.x <= sq.center.x && diamond.center.y > sq.center.y {
                    if outOfRange(index-1)
                        && outOfRange(index+10)
                        && outOfRange(index+9)
                    {
                        return true
                    }else{
                        return false
                    }
                }else if diamond.center.x > sq.center.x && diamond.center.y <= sq.center.y {
                    if outOfRange(index+1)
                        && outOfRange(index-10)
                        && outOfRange(index)
                    {
                        return true
                    }else{
                        return false
                    }
                }else if diamond.center.x > sq.center.x && diamond.center.y > sq.center.y {
                    if outOfRange(index+10)
                        && outOfRange(index+11)
                        && outOfRange(index)
                    {
                        return true
                    }else{
                        return false
                    }
                }
            case .RightDown:
                if diamond.center.x <= sq.center.x && diamond.center.y <= sq.center.y {
                    if outOfRange(index-11)
                        && outOfRange(index-1)
                        && outOfRange(index-10)
                    {
                        return true
                    }else{
                        return false
                    }
                }else if diamond.center.x <= sq.center.x && diamond.center.y > sq.center.y {
                    if outOfRange(index-1)
                        && outOfRange(index+9)
                        && outOfRange(index)
                    {
                        return true
                    }else{
                        return false
                    }
                }else if diamond.center.x > sq.center.x && diamond.center.y <= sq.center.y {
                    if outOfRange(index-9)
                        && outOfRange(index-10)
                        && outOfRange(index)
                    {
                        return true
                    }else{
                        return false
                    }
                }else if diamond.center.x > sq.center.x && diamond.center.y > sq.center.y {
                    if outOfRange(index+10)
                        && outOfRange(index+1)
                        && outOfRange(index)
                    {
                        return true
                    }else{
                        return false
                    }
                }
            default : break
            }
        case .D4:
            switch direction {
            case .Vertical:
                if diamond.center.y > sq.center.y {
                    if outOfRange(index)
                        && outOfRange(index-10)
                        && outOfRange(index+10)
                        && outOfRange(index+20) {
                            return true
                    }else{
                        return false
                    }
                }else if diamond.center.y <= sq.center.y {
                    if outOfRange(index)
                        && outOfRange(index-10)
                        && outOfRange(index+10)
                        && outOfRange(index-20) {
                            return true
                    }else{
                        return false
                    }
                }
            case .Horizontal:
                if diamond.center.x <= sq.center.x {
                    if outOfRange(index)
                        && outOfRange(index-1)
                        && outOfRange(index+1)
                        && outOfRange(index-2)
                    {
                        return true
                    }else{
                        return false
                    }
                }else if diamond.center.x > sq.center.x {
                    if outOfRange(index)
                        && outOfRange(index-1)
                        && outOfRange(index+1)
                        && outOfRange(index+2)
                    {
                        return true
                    }else{
                        return false
                    }
                }
            case .None:
                if diamond.center.x <= sq.center.x && diamond.center.y <= sq.center.y {
                    if outOfRange(index)
                        && outOfRange(index-1)
                        && outOfRange(index-11)
                        && outOfRange(index-10)
                        
                    {
                        return true
                    }else{
                        return false
                    }
                }else if diamond.center.x <= sq.center.x && diamond.center.y > sq.center.y {
                    if outOfRange(index)
                        && outOfRange(index-1)
                        && outOfRange(index+9)
                        && outOfRange(index+10)
                        
                    {
                        return true
                    }else{
                        return false
                    }
                }else if diamond.center.x > sq.center.x && diamond.center.y <= sq.center.y {
                    if outOfRange(index)
                        && outOfRange(index+1)
                        && outOfRange(index-10)
                        && outOfRange(index-9)
                        
                    {
                        return true
                    }else{
                        return false
                    }
                }else if diamond.center.x > sq.center.x && diamond.center.y > sq.center.y {
                    if outOfRange(index)
                        && outOfRange(index+1)
                        && outOfRange(index+11)
                        && outOfRange(index+10)
                        
                    {
                        return true
                    }else{
                        return false
                    }
                }
            default :break
            }
        case .D5:
            switch direction {
            case .Vertical:
                if outOfRange(index+10)
                    && outOfRange(index+20)
                    && outOfRange(index-10)
                    && outOfRange(index-20)
                    && outOfRange(index) {
                        return true
                }else{
                    return false
                }
            case .Horizontal:
                if outOfRange(index+1)
                    && outOfRange(index+2)
                    && outOfRange(index-1)
                    && outOfRange(index-2)
                    && outOfRange(index)
                    
                {
                    return true
                }else{
                    return false
                }
            case .LeftUp:
                if outOfRange(index+9)
                    && outOfRange(index-9)
                    && outOfRange(index+11)
                    && outOfRange(index+1)
                    && outOfRange(index+10)
                    
                {
                    return true
                }else{
                    return false
                }
            case .LeftDown:
                if outOfRange(index-10)
                    && outOfRange(index-9)
                    && outOfRange(index-11)
                    && outOfRange(index+1)
                    && outOfRange(index+11)
                    
                {
                    return true
                }else{
                    return false
                }
            case .RightUp:
                if outOfRange(index-1)
                    && outOfRange(index-11)
                    && outOfRange(index+11)
                    && outOfRange(index+9)
                    && outOfRange(index+10)
                {
                    return true
                }else{
                    return false
                }
            case .RightDown:
                if outOfRange(index-1)
                    && outOfRange(index-11)
                    && outOfRange(index-10)
                    && outOfRange(index-9)
                    && outOfRange(index+9)
                {
                    return true
                }else{
                    return false
                }
            default :break
            }
        case .D9:
            switch direction {
            case .None:
                if outOfRange(index+1)
                    && outOfRange(index-1)
                    && outOfRange(index-10)
                    && outOfRange(index+10)
                    && outOfRange(index+11)
                    && outOfRange(index-11)
                    && outOfRange(index)
                    && outOfRange(index-9)
                    && outOfRange(index+9)
                {
                    return true
                }else{
                    return false
                }
            default:break
            }
        //default :break
        }
        return false
    }
    
    //MARK: 查看是否越界 和 该位置状态
    func outOfRange(_ index:Int) -> Bool {
        if index >= 0 && index <= 99 {
            if squareStatus[index] == 0 {
                return true
            }
        }
        return false
    }
    
    //MARK: 在棋盘上创建新的方块
    func produceSqure(_ index:Int) {
        let sq = squares[index]
        let newSq = UIView(frame: CGRect(x: 0, y: 0, width: sq.frame.size.width, height: sq.frame.size.height))
        newSq.backgroundColor=color()
        newSq.center=sq.center
        newSq.layer.borderColor=UIColor.white.cgColor
        newSq.layer.borderWidth=1
        newSq.layer.masksToBounds=true
        newSq.layer.cornerRadius=4
        newSq.tag = NEWSQUARE_TAG+index
        selfView.addSubview(newSq)
        
        newSquares.append(newSq)
        
        squareStatus[index]=1
    }
    
    var fill_Is : [Int]=[] //记录横向
    var fill_Js : [Int]=[] //记录纵向
    
    //MARK: 检测纵横向 满行 时 对应的 行数 i  列数 j
    func checkFillNumber() -> Int {
        //遍历状态数组
        for i in 0...9 {
            
            var cnt_i = 0
            
            var cnt_j = 0
            
            for j in 0...9 {
                
                if squareStatus[i*10+j]==1 {
                    if cnt_i==9 && !hasIndexForI(i: i) {
                        fill_Is.append(i)
                    }
                    cnt_i += 1
                }
                
                if squareStatus[i+10*j]==1 {
                    if cnt_j==9 && !hasIndexForJ(j: i) {
                        fill_Js.append(i)
                    }
                    cnt_j += 1
                }
            }
        }
        
        print("i = \(fill_Is) j = \(fill_Js)")
        return fill_Is.count + fill_Js.count
    }
    
    //该行是否记录过
    func hasIndexForI(i:Int) -> Bool {
        for n in fill_Is {
            if n==i {
                return true
            }
        }
        return false
    }
    //该列是否记录过
    func hasIndexForJ(j:Int) -> Bool {
        for n in fill_Js {
            if n==j {
                return true
            }
        }
        return false
    }
    
    //MARK: 消除满行
    func clearFillSquares() {
        
        //消除横行
        if fill_Is.count > 0 {
            for i in fill_Is {
                for y in 0...9 {
                    print("i= \(i) tag = \(NEWSQUARE_TAG + i*10+y)")
                    for sq in newSquares {
                        if sq.tag == NEWSQUARE_TAG + i*10 + y {//如果存在
                            //移除动画
                            UIView.animate(withDuration: 0.1, delay: 0.03*Double(y), options: [], animations: { () -> Void in
                                sq.transform=CGAffineTransform(scaleX: 1.2, y: 1.2)
                                }, completion: { (finished) -> Void in
                                    UIView.animateKeyframes(withDuration: 0.2, delay: 0, options: [], animations: { () -> Void in
                                        sq.transform=CGAffineTransform(scaleX: 0.3, y: 0.3)
                                        }, completion: { (finished) -> Void in
                                            squareStatus[i*10 + y]=0
                                            sq.removeFromSuperview()
                                            
                                    })
                            })
                        }
                    }
                }
            }
        }
        
        //消除纵行
        if fill_Js.count > 0 {
            for j in fill_Js {
                for x in 0...9 {
                    for sq in newSquares {
                        print("i= \(j) tag = \(NEWSQUARE_TAG + j+x*10)")
                        if sq.tag == NEWSQUARE_TAG + j + x*10 {//如果存在
                            //移除动画
                            UIView.animate(withDuration: 0.1, delay: 0.03*Double(x), options: [], animations: { () -> Void in
                                sq.transform=CGAffineTransform(scaleX: 1.2, y: 1.2)
                                }, completion: { (finished) -> Void in
                                    UIView.animateKeyframes(withDuration: 0.2, delay: 0, options: [], animations: { () -> Void in
                                        sq.transform=CGAffineTransform(scaleX: 0.3, y: 0.3)
                                        }, completion: { (finished) -> Void in
                                            squareStatus[j + x*10]=0
                                            sq.removeFromSuperview()
                                            
                                    })
                            })
                        }
                    }
                }
            }
        }
    }
    
    //闭包传递函数
    //为空时
    func emptyCallBack(callBack:@escaping ()->()) {
        isEmpty=callBack
    }
    func gameOverCallBack(callBack:@escaping ()->()) {
        gameOver=callBack
    }
    func reloadScoreCallBack(callBack:@escaping ()->()) {
        reloadScore=callBack
    }
    
    //MARK: 删除该元素
    func removeFromDiamonds(){
        var i = 0
        for d in diamonds {
            if d.tag == self.tag {
                diamonds.remove(at: i)
                return
            }
            i += 1
        }
    }
    
    
    //MARK: 放大比例
    func scale() -> CGFloat {
        //算出放大比例
        let scale = sqWidth()/diamondWidth
        return scale
    }
    
    //MARK: 变大
    func enlarge() {
        //println("原本小方块大小 \(diamondWidth) \n Diamond宽 \(self.frame.width) \n Diamond高 \(self.frame.height)")
        
        selfView.insertSubview(self, at: selfView.subviews.count)
        
        UIView.animate(withDuration: 0.2, animations: {
            self.transform=CGAffineTransform(scaleX: self.scale(), y: self.scale())
            }) { (finished) -> Void in
                //println("现在小方块大小 Diamond宽 \(self.frame.width) \n Diamond高 \(self.frame.height)")
        }
        
        UIView.animate(withDuration: 0.3, animations: {
            self.center.y = self.center.y - self.frame.size.height/2.0
            }) { (finished) -> Void in
                
        }
        
    }
    
    //MARK: 还原
    func resume() {
        //恢复原本位置
        //println("ori center \(originalCenter!.x , originalCenter!.y)")
        
        UIView.animate(withDuration: 0.1, animations: {
            self.center = self.originalCenter
            }) { (finished) -> Void in
                
        }
        //恢复大小
        
        UIView.animate(withDuration: 0.2, animations: {
            self.transform=CGAffineTransform(scaleX: 1, y: 1)
            }) { (finished) -> Void in
                
        }
    }
}
